/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiWindowW32.cpp
	Implements the MaxsiWindowSystem using the W32 platform.

******************************************************************************/

#include "MaxsiLibrary.h"

#ifdef Maxsi_Support_W32

#include <windowsx.h>
#include "commctrl.h"

BeginMaxsiNamespace

HFONT DefaultFont			=	NULL;
HFONT DefaultFontBold		=	NULL;
HFONT DefaultFontLabel		=	NULL;
HFONT DefaultFontButton		=	NULL;

LRESULT CALLBACK MaxsiWindowSystemW32Proc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{ 
	switch (uMsg) 
    { 
		case WM_CREATE: 
		{ 
			// Initialize the window. 
            return 0; 
		}
		case WM_PAINT: 
		{
			PAINTSTRUCT PaintStructure;
			
			BeginPaint(hwnd, &PaintStructure);

			EndPaint(hwnd, &PaintStructure);

            return 0; 
		}
		case WM_SIZE:
		{
            // Set the size and position of the window. 
            return 0; 
		}
		case WM_DESTROY: 
		{        
			// Clean up window-specific data objects. 
			PostQuitMessage(0);
            return 0; 
		}
        // 
        // Process other messages. 
        // 
 
        default: 
            return DefWindowProcM(hwnd, uMsg, wParam, lParam); 
    } 
    return 0; 
} 

MaxsiWindowSystemW32::MaxsiWindowSystemW32()
{
	
}

MaxsiWindowSystemW32::~MaxsiWindowSystemW32()
{
	if ( ControlSystem ) { DeleteControlSystem(ControlSystem); }
	if ( DefaultFont != NULL ) { DeleteObject(DefaultFont); }
	if ( DefaultFontBold != NULL ) { DeleteObject(DefaultFont); }
	if ( DefaultFontLabel != NULL ) { DeleteObject(DefaultFontLabel); }
	if ( DefaultFontButton != NULL ) { DeleteObject(DefaultFontButton); }
}

MaxsiControlSystem* MaxsiWindowSystemW32::GetControlSystem()
{
	if ( ControlSystem == NULL ) { ControlSystem = CreateControlSystem(); }

	if ( ControlSystem ) { ControlSystem->SetWindowSystem(this); }

	return ControlSystem;
}

MaxsiControlSystem* MaxsiWindowSystemW32::CreateControlSystem()
{
	return new MaxsiControlSystemW32;
}

bool MaxsiWindowSystemW32::DeleteControlSystem(MaxsiControlSystem* ControlSystem)
{
	delete (MaxsiControlSystemW32*)ControlSystem;
	return true;
}

int MaxsiWindowSystemW32::Initialize(int* argc, char*** argv)
{
	INITCOMMONCONTROLSEX CommonControlsInitStruct;

	CommonControlsInitStruct.dwSize		=	sizeof(CommonControlsInitStruct);
	CommonControlsInitStruct.dwICC		=	ICC_PROGRESS_CLASS;

	if ( InitCommonControlsEx(&CommonControlsInitStruct) == FALSE ) { MAXSI_TODO("Add error handling!"); }

	if ( DefaultFont != NULL ) { DeleteObject(DefaultFont); }
	if ( DefaultFontBold != NULL ) { DeleteObject(DefaultFont); }
	if ( DefaultFontLabel != NULL ) { DeleteObject(DefaultFontLabel); }
	if ( DefaultFontButton != NULL ) { DeleteObject(DefaultFontButton); }

	DefaultFont = CreateFontM(13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
		DEFAULT_PITCH | FF_SWISS, _MESTR("Verdana"));

	DefaultFontBold = CreateFontM(13, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
		DEFAULT_PITCH | FF_SWISS, _MESTR("Verdana"));

	DefaultFontLabel = CreateFontM(13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
		DEFAULT_PITCH | FF_SWISS, _MESTR("Verdana"));

	DefaultFontButton = CreateFontM(10, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
		DEFAULT_PITCH | FF_SWISS, _MESTR("MS Sans Serif"));

	WNDCLASSW  WindowClass = {0};

	WindowClass.lpfnWndProc = (WNDPROC)MaxsiWindowSystemW32Proc;
	WindowClass.hInstance = (HINSTANCE)GetModuleHandle(NULL);
	WindowClass.hIcon = (HICON)LoadImageM(NULL, _MESTR("../Images/MaxsiIcon.ico"), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
	//WindowClass.hIcon = LoadIconM((HINSTANCE)hInstance, _MESTR("ProductIcon"));
	WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WindowClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
	WindowClass.lpszClassName = _MESTR("MaxsiWindowSystemW32Window");

	if (!RegisterClassM(&WindowClass)) { return FALSE; }

	return 1;
}

int MaxsiWindowSystemW32::MainLoop()
{
	MSG		msg			=	{0};
	BOOL	bRet		=	FALSE;

	// Begin the mainloop
	while( (bRet = GetMessageM( &msg, NULL, 0, 0 )) != 0)
	{ 
		if ( bRet == -1 ) { break; }

		TranslateMessage(&msg);
		DispatchMessageM(&msg); 
	}

	return (int)msg.wParam;
}

MaxsiHandle MaxsiWindowSystemW32::CreateWindow(MaxsiHandle Parent, int Width, int Height, int Left, int Top, MESTR* Title)
{
	return (MaxsiHandle)CreateWindowM(
        _MESTR("MaxsiWindowSystemW32Window"),
        Title,
        (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX),
        Left, Top,
        Width, Height,
        (HWND)Parent, NULL, GetModuleHandle(NULL), NULL );
}

MaxsiError MaxsiWindowSystemW32::GetWindowSize(MaxsiHandle Window, int* Left, int* Top, int* Width, int* Height)
{
	RECT ClientArea;

	if ( GetClientRect((HWND)Window, &ClientArea) == 0 ) { return W32Error2MaxsiError(GetLastError()); }
	
	if ( Left )		{ *Left		=	ClientArea.left; }
	if ( Top )		{ *Top 		=	ClientArea.top; }
	if ( Width )	{ *Width	=	ClientArea.right; }
	if ( Height )	{ *Height	=	ClientArea.bottom; }

	return MAXSI_ERROR_SUCCESS;
}

bool MaxsiWindowSystemW32::ShowWindow(MaxsiHandle Window)
{
	return (::ShowWindow((HWND)Window, SW_SHOW) != FALSE);
}

bool MaxsiWindowSystemW32::HideWindow(MaxsiHandle Window)
{
	return (::ShowWindow((HWND)Window, SW_HIDE) != FALSE);
}

MaxsiError MaxsiWindowSystemW32::UpdateWindow(MaxsiHandle Window)
{
	return (InvalidateRect((HWND)Window, NULL, TRUE) != 0) ? MAXSI_ERROR_SUCCESS : W32Error2MaxsiError(GetLastError());
}

MaxsiHandle MaxsiWindowSystemW32::CreatePictureBufferFromFile(MESTR* FileName)
{
	return NULL; // MAXSI_ERROR_NOT_IMPLEMENTED
}

bool MaxsiWindowSystemW32::DeletePictureBuffer(MaxsiHandle PictureBuffer)
{
	return true;
}

bool MaxsiWindowSystemW32::SetWindowIcon(MaxsiHandle Window, MaxsiHandle Icon)
{
	return true; // MAXSI_ERROR_NOT_IMPLEMENTED
}

int MaxsiWindowSystemW32::MoveWindowControl(MaxsiHandle Parent, MaxsiHandle Control, int Top, int Left, int Width, int Height, bool UnusedInLinux)
{
	return (MoveWindow((HWND)Control, Top, Left, Width, Height, TRUE) != FALSE);
}

int MaxsiWindowSystemW32::MsgBox(MaxsiHandle Parent, int Flags, MESTR* ErrorMessage, MESTR* ErrorTitle)
{	
	return MessageBoxM((HWND)Parent, ErrorMessage, ErrorTitle, MB_OK | MB_ICONEXCLAMATION);
}

MaxsiHandle MaxsiWindowSystemW32::GetDefaultBoldFont()
{
	return (MaxsiHandle)DefaultFontBold;
}


bool MaxsiControlSystemW32::DeleteControl(MaxsiHandle Control)
{
	DestroyWindow((HWND)Control);
	return true;
}

MaxsiHandle MaxsiControlSystemW32::CreateFrame(MaxsiHandle Parent)
{
	HWND NewControl = CreateWindowM(_MESTR("STATIC"), NULL, WS_VISIBLE | WS_CHILD | SS_LEFT, 0, 0, 0, 0, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);

	return (MaxsiHandle)NewControl;
}

MaxsiHandle MaxsiControlSystemW32::CreateLabel(MaxsiHandle Parent)
{
	HWND NewControl = CreateWindowM(_MESTR("STATIC"), NULL, WS_VISIBLE | WS_CHILD | SS_LEFT, 100, 100, 100, 100, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);

	if ( NewControl != NULL ) { SendMessageM(NewControl, WM_SETFONT, (WPARAM)DefaultFontLabel, TRUE); }

	return (MaxsiHandle)NewControl;
}

MaxsiHandle MaxsiControlSystemW32::CreateButton(MaxsiHandle Parent)
{
	HWND NewControl = CreateWindowM(_MESTR("BUTTON"), _MESTR("Hello World!"), WS_VISIBLE | WS_CHILD, 100, 100, 100, 100, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);

	if ( NewControl != NULL ) { SendMessageM(NewControl, WM_SETFONT, (WPARAM)DefaultFontButton, TRUE); }

	return (MaxsiHandle)NewControl;
}

MaxsiHandle MaxsiControlSystemW32::CreateTextSingleLine(MaxsiHandle Parent)
{
	HWND NewControl = CreateWindowM(_MESTR("EDIT"), NULL, WS_VISIBLE | WS_CHILD | SS_LEFT | WS_BORDER |
	ES_LEFT | ES_AUTOHSCROLL, 100, 100, 100, 100, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);

	if ( NewControl != NULL ) { SendMessageM(NewControl, WM_SETFONT, (WPARAM)DefaultFont, TRUE); }

	return (MaxsiHandle)NewControl;
}

MaxsiHandle MaxsiControlSystemW32::CreateTextMultiLine(MaxsiHandle Parent)
{
	return CreateButton(Parent);
}

MaxsiHandle MaxsiControlSystemW32::CreateRadioButton(MaxsiHandle Parent)
{
	return CreateButton(Parent);
}

MaxsiHandle MaxsiControlSystemW32::CreateCheckButton(MaxsiHandle Parent)
{
	return CreateButton(Parent);
}

MaxsiHandle MaxsiControlSystemW32::CreateProgressBar(MaxsiHandle Parent)
{
	return (MaxsiHandle)CreateWindowM(_MESTR("msctls_progress32"), NULL, WS_VISIBLE | WS_CHILD | PBS_SMOOTH, 0, 0, 0, 0, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);
}

MaxsiHandle MaxsiControlSystemW32::CreateTreeView(MaxsiHandle Parent)
{
	return CreateButton(Parent);
}

MaxsiHandle MaxsiControlSystemW32::CreateListView(MaxsiHandle Parent)
{
	return CreateButton(Parent);
}

MaxsiHandle MaxsiControlSystemW32::CreateSeparatorH(MaxsiHandle Parent)
{
	HWND NewControl = CreateWindowM(_MESTR("STATIC"), NULL, WS_VISIBLE | WS_CHILD | SS_LEFT, 0, 0, 0, 0, (HWND)Parent, NULL, (HINSTANCE)GetWindowLongPtr((HWND)Parent, GWLP_HINSTANCE), NULL);

	if ( NewControl != NULL ) { SendMessageM(NewControl, WM_SETFONT, (WPARAM)DefaultFont, TRUE); }

	return (MaxsiHandle)NewControl;
}

bool MaxsiControlSystemW32::SetLabelText(MaxsiHandle Control, MESTR* Text)
{
	return (SetWindowTextM((HWND)Control, Text) != 0);
}

bool MaxsiControlSystemW32::SetLabelFont(MaxsiHandle Control, MaxsiHandle Font)
{
	SendMessageM((HWND)Control, WM_SETFONT, (WPARAM)Font, TRUE);

	return true;
}

bool MaxsiControlSystemW32::SetButtonText(MaxsiHandle Control, MESTR* Text)
{
	return (SetWindowTextM((HWND)Control, Text) != 0);
}

bool MaxsiControlSystemW32::SetProgress(MaxsiHandle Control, float Progress, size_t Type)
{
	if ( Type == MAXSI_PROGRESS_CURRENT )
	{
		SendMessageM((HWND)Control, PBM_SETPOS, (int)(Progress*100.0f), 0);
	}
	else if ( Type == MAXSI_PROGRESS_NORMAL )
	{
		SetWindowLongPtr((HWND)Control, GWL_STYLE, WS_VISIBLE | WS_CHILD | PBS_SMOOTH);
		SendMessageM((HWND)Control, PBM_SETMARQUEE, FALSE, 0);
		SendMessageM((HWND)Control, PBM_SETSTATE, PBST_NORMAL, 0);
		SendMessageM((HWND)Control, PBM_SETPOS,(WPARAM)(int)(Progress*100.0f),(LPARAM)0);
	}
	else if ( Type == MAXSI_PROGRESS_INDETERMINATE )
	{
		SetWindowLongPtr((HWND)Control, GWL_STYLE, WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_MARQUEE);
		SendMessageM((HWND)Control, PBM_SETSTATE, PBST_NORMAL, 0);
		SendMessageM((HWND)Control, PBM_SETMARQUEE, TRUE, 0);
		SendMessageM((HWND)Control, PBM_SETPOS, (int)(Progress*100.0f), 0);
	}
	else if ( Type == MAXSI_PROGRESS_ERROR )
	{
		SetWindowLongPtr((HWND)Control, GWL_STYLE, WS_VISIBLE | WS_CHILD | PBS_SMOOTH);
		SendMessageM((HWND)Control, PBM_SETMARQUEE, FALSE, 0);
		SendMessageM((HWND)Control, PBM_SETPOS,(WPARAM)100, (LPARAM)0);
		SendMessageM((HWND)Control, PBM_SETSTATE, PBST_ERROR, 0);
	}
	else if ( Type == MAXSI_PROGRESS_PAUSED )
	{
		SetWindowLongPtr((HWND)Control, GWL_STYLE, WS_VISIBLE | WS_CHILD | PBS_SMOOTH);
		SendMessageM((HWND)Control, PBM_SETMARQUEE, FALSE, 0);
		SendMessageM((HWND)Control, PBM_SETPOS,(WPARAM)100, (LPARAM)0);
		SendMessageM((HWND)Control, PBM_SETSTATE, PBST_PAUSED, 0);
	}
	else
	{
		return false;
	}

	return true;
}

EndMaxsiNamespace

#endif

